home *** CD-ROM | disk | FTP | other *** search
/ Network Supervisor's Toolkit / Network Supervisor's Toolkit.iso / tools / nwbcas / nwbcast.asm < prev    next >
Assembly Source File  |  1996-07-10  |  13KB  |  281 lines

  1. ;*****************************************************************************
  2. ; PROGRAM ----: NWBCAST.ASM, version 1.0 
  3. ; AUTHOR -----: Kevin E. Saffer, 904-296-9000 Days EST, 262-1020 Evenings
  4. ; COPYRIGHT --: None, placed into the public domain
  5. ; CREATED ----: 1/22/1994 at 13:04
  6. ;*****************************************************************************
  7. ; Introduction:
  8. ; -------------
  9. ; Implements a software interrupt service routine for the Novell shell
  10. ; versions 3.01 and above.  The interrupt handler will insert a programmer
  11. ; specified keystroke into the PC's keyboard buffer whenever a broadcast
  12. ; message is detected.  The Clipper application may then handle this event
  13. ; by defining a SET KEY procedure tied to the keystroke specified in the 
  14. ; install routine.  The Clipper procedure may then use the NETTO functions
  15. ; to handle the incoming message.
  16. ;
  17. ; Warning:  This routine installs a ISR (interrupt service routine) which
  18. ;           MUST be removed before program exit by calling the uninstall 
  19. ;           function.  Leaving the ISR active after program completion will
  20. ;           cause the computer to transfer control to an incorrect address
  21. ;           the next time a broadcast message is detected.  This will most
  22. ;           likely result in a locked up PC.  A future version can be built
  23. ;           as a small TSR loaded before the Clipper application.  This will
  24. ;           allow the routine to remain in memory even if the Clipper pgm
  25. ;           crashes.  An interface module will be linked into the Clipper
  26. ;           application to communicate with the TSR.  After this release is
  27. ;           debugged, I'll get to work on the TSR version.
  28. ;
  29. ; Since an ISR is used, this module may never be overlayed.  The ISR code
  30. ; must always be available to handle the interrupt, therefore this object
  31. ; file must be placed into the root portion of your link script.  It will
  32. ; only increase the load size of the application by 700 bytes.
  33. ;
  34. ; Compatibility:
  35. ; --------------
  36. ; Netware shell versions 3.01 and above will issue an INT 2F whenever a 
  37. ; broadcast message is waiting.  For this reason, the latest shells must be 
  38. ; used; they are available for downloading on the Compuserve NOVLIB forum.
  39. ;
  40. ; This routine will not work with the DOS extenders from CA or Blinker.  The
  41. ; reason it will not work is that I have no idea how to switch these routines
  42. ; from segment addressing over to protected mode addressing.  If anyone has
  43. ; this knowledge, please share it on the forum or call me directly.
  44. ;
  45. ; Usage Restrictions:
  46. ; -------------------
  47. ; Should you wish to shell out of the Clipper application, this routine must
  48. ; be shut down using NB_STOP() prior to running other programs.  If left 
  49. ; active, any broadcast message will cause the specified keystroke to be
  50. ; fed into the shelled program.  Re-start the routine using NB_START() when
  51. ; the Clipper application regains control.
  52. ;
  53. ; Messages Must Be Allowed! (CASTON)
  54. ; ----------------------------------
  55. ; Before use, you should change the Netware shell's brodcast mode to 0 to 
  56. ; allow normal broadcast message handling.  This routine will then prevent
  57. ; the message from being displayed on the last display line.  Use the NETTO
  58. ; function FN_SETBMOD( 0 ) to accomplish this, or ensure CASTON has been
  59. ; executed prior to loading your application.
  60. ;
  61. ; Compiling/Linking:
  62. ; ------------------
  63. ; Compile with MASM 5.1 or greater using "MASM nwbcast;"
  64. ; Link the resulting NWBCAST.OBJ into your application at the root level.
  65. ;
  66. ;*****************************************************************************
  67. ; Clipper callable function list:
  68. ;*****************************************************************************
  69. ;
  70. ; NB_START( <key> ) - installs the interrupt service routine with specified key
  71. ; NB_STOP()         - removes the interrupt service routine
  72. ; NB_SERVER()       - returns the connection ID of the server holding the last message
  73. ;
  74. ;*****************************************************************************
  75. .RADIX 16  ; my family has 8 fingers per hand so we think in HEX! <g>
  76.  
  77. ; declare callable routines as public
  78.         PUBLIC NB_START        ; installation routine
  79.         PUBLIC NB_STOP         ; uninstallation routine
  80.         PUBLIC NB_SERVER       ; last message server connection number
  81.  
  82. ; declare clipper parameter routines
  83.         EXTRN   __PARC:FAR    ; get character string, segment:offset in DX:AX
  84.         EXTRN   __PARCLEN:FAR    ; get length of a string parameter into ax
  85.         EXTRN   __PARCSIZ:FAR    ; get size of memory allocated for string parameter
  86.         EXTRN   __PARDS:FAR    ; get date string, segment:offset in DX:AX
  87.         EXTRN   __PARINFA:FAR    ; get size of array parameter or element type
  88.         EXTRN   __PARINFO:FAR    ; get number of parameters or type of one
  89.         EXTRN   __PARL:FAR    ; get logical, value in AX
  90.         EXTRN   __PARND:FAR    ; get numeric double, segment:offset in DX:AX
  91.         EXTRN   __PARNI:FAR    ; get numeric integer, value in AX
  92.         EXTRN   __PARNL:FAR    ; get numeric long, value in DX:AX
  93.         EXTRN   __RETC:FAR    ; return string, push seg:off onto stack
  94.         EXTRN   __RETCLEN:FAR    ; return string of x length, push seg:off:length
  95.         EXTRN   __RETDS:FAR    ; return date string, push seg:off onto stack
  96.         EXTRN   __RETL:FAR    ; return logical, push 1 register onto stack
  97.         EXTRN   __RETND:FAR    ; return double, push 4 registers onto stack
  98.         EXTRN   __RETNI:FAR    ; return integer, push 1 register onto stack
  99.         EXTRN   __RETNL:FAR    ; return long, push 2 registers onto stack
  100.  
  101. ; define a keyboard buffer structure for the insertion routine
  102. BIOS_DATA SEGMENT AT 40
  103.         ORG             1A
  104.         BUFFER_HEAD     DW   ?  ; pointer to the keybord buffer head
  105.         BUFFER_TAIL     DW   ?  ; pointer to the keyboard buffer tail
  106.         ORG             80 
  107.         BUFFER_START    DW   ?  ; starting keyboard buffer address
  108.         BUFFER_END      DW   ?  ; ending keyboard buffer address
  109. BIOS_DATA ENDS
  110.  
  111. ; declare our code segment
  112. CODE SEGMENT 'CODE'
  113.         ASSUME  CS:CODE,DS:CODE      ; inform MASM of our intentions
  114.  
  115.         OLDINTSEG       DW   0       ; old 2F vector segment
  116.         OLDINTOFF       DW   0       ; old 2F vector offset
  117.         KEYCODE         DW   1       ; keyboard scan code to be inserted (this is Ctrl-A)
  118.         SERVERID        DW   0       ; server connection number
  119.  
  120. ;*****************************************************************************
  121. ; NB_START() - interrupt service routine installation
  122. ;*****************************************************************************
  123. NB_START PROC FAR
  124.         PUSH    BP              ; save vital registers
  125.         MOV     BP,SP          
  126.         PUSH    DS             
  127.         PUSH    ES            
  128.  
  129.         MOV     AX,1            ; retrieve the keycode to be used
  130.         PUSH    AX                 
  131.         CALL    __PARNI        
  132.         MOV     CS:KEYCODE,AX   ; save it and restore the stack
  133.         POP     AX
  134.  
  135.         PUSH    CS              ; reset the data segment to point to our code segment
  136.         POP     DS
  137.  
  138.         CMP     OLDINTSEG,0     ; check to see if the vector was already changed
  139.         JZ      NB_START1       ; no, proceed with vector change
  140.  
  141.         POP     ES              ; restore clipper registers
  142.         POP     DS             
  143.         POP     BP             
  144.         CLD                     ; reset the direction flag
  145.         RET                     ; return to clipper          
  146.  
  147. NB_START1:
  148.         MOV     AX,352F                 ; get interrupt vector 2F into ES:BX
  149.         INT     21                      ; call dos
  150.         MOV     OLDINTSEG,ES            ; save the existing handler segment
  151.         MOV     OLDINTOFF,BX            ; save the existing handler offset
  152.         MOV    WORD PTR [INTADDR+2],ES    ; update ISR with existing segment
  153.         MOV    WORD PTR [INTADDR],BX    ; update ISR with existing offset
  154.  
  155.         PUSH    CS                      ; store the segment of new routine
  156.         POP     DS                      ; and place it into DS
  157.         MOV     DX,OFFSET NB_INT2F      ; offset of the new routine to DX
  158.         MOV     AX,252F                 ; set interrupt vector 2F from DS:DX
  159.         INT     21                      ; call dos
  160.  
  161.         POP     ES              ; restore clipper registers
  162.         POP     DS             
  163.         POP     BP             
  164.         CLD                     ; reset the direction flag
  165.         RET                     ; return to clipper          
  166.  
  167. NB_START ENDP
  168.  
  169. ;*****************************************************************************
  170. ; NB_STOP() - interrupt service routine uninstallation
  171. ;*****************************************************************************
  172. NB_STOP PROC FAR
  173.         PUSH    BP              ; save vital registers
  174.         MOV     BP,SP          
  175.         PUSH    DS             
  176.         PUSH    ES            
  177.  
  178.         PUSH    CS              ; reset the data segment to point to our code segment
  179.         POP     DS
  180.  
  181.         CMP     OLDINTSEG,0     ; check to see if the vector had been changed
  182.         JZ      NB_STOP2        ; no, return to clipper
  183.  
  184.         MOV     AX,OLDINTSEG    ; retrieve old routine segment
  185.         MOV     DX,OLDINTOFF    ; retrieve old routine offset
  186.  
  187.         PUSH    AX              ; store the segment of old routine
  188.         POP     DS              ; and place it into DS
  189.         MOV     AX,252F         ; set interrupt vector 2F from DS:DX
  190.         INT     21              ; call dos
  191.  
  192.         MOV     OLDINTSEG,0     ; clear the existing handler segment
  193.         MOV     OLDINTOFF,0     ; clear the existing handler offset
  194.  
  195. NB_STOP2:
  196.         POP     ES              ; restore clipper registers
  197.         POP     DS             
  198.         POP     BP             
  199.         CLD                     ; reset the direction flag
  200.         RET                     ; return to clipper          
  201.  
  202. NB_STOP ENDP
  203.  
  204. ;*****************************************************************************
  205. ; NB_SERVER() - return the connection ID of the server holding the message
  206. ;*****************************************************************************
  207. NB_SERVER PROC FAR
  208.         PUSH    BP              ; save vital registers
  209.         MOV     BP,SP          
  210.         PUSH    DS             
  211.         PUSH    ES            
  212.  
  213.         MOV     AX,CS:SERVERID  ; retrieve the connection number
  214.         PUSH    AX                 
  215.         CALL    __RETNI        
  216.         POP     AX
  217.  
  218.         POP     ES              ; restore clipper registers
  219.         POP     DS             
  220.         POP     BP             
  221.         CLD                     ; reset the direction flag
  222.         RET                     ; return to clipper          
  223.  
  224. NB_SERVER ENDP
  225.  
  226. ;*****************************************************************************
  227. ; NB_INT2F - interrupt service routine
  228. ;*****************************************************************************
  229. NB_INT2F PROC NEAR
  230.     PUSHF                ; save calller's flags for the original interrupt 2F
  231.     CMP     AX,7A85      ; is a broadcast message is waiting?
  232.     JE     NB_INT2F1    ; yes, take over the interrupt
  233.     JMP    NB_INT2F4    ; no, transfer control to the original interrupt 
  234.  
  235. NB_INT2F1:
  236.     PUSH    AX               ; save the registers used by this routine
  237.         PUSH    BX
  238.         PUSH    DX
  239.         PUSH    DS
  240.  
  241.     PUSH    CS             ; set DS to this segment
  242.     POP    DS
  243.     CLD                      ; clear direction flag
  244.         MOV     CS:SERVERID,CX   ; save the server connection number for later
  245.         XOR     CX,CX            ; inform Netware we will handle the message
  246.         MOV     BX,BIOS_DATA     ; point ds to the bios data area
  247.         MOV     DS,BX            
  248.         ASSUME  DS:BIOS_DATA     ; inform MASM of the new data segment
  249.         CLI                      ; disable interrupts for buffer manipulation
  250.         MOV     BX,BUFFER_TAIL   ; get buffer tail address
  251.         MOV     DX,BX            ; transfer it to DX
  252.         ADD     DX,2             ; calculate next buffer position
  253.         CMP     DX,BUFFER_END    ; did we overshoot the end?
  254.         JNE     NB_INT2F2        ; no, then continue
  255.         MOV     DX,BUFFER_START  ; yes, then wrap to start of buffer
  256.  
  257. NB_INT2F2:
  258.         CMP     DX,BUFFER_HEAD   ; is the buffer full?
  259.         JE      NB_INT2F3        ; yes, then end now
  260.         MOV     AX,CS:KEYCODE    ; retrieve the keycode
  261.         MOV     [BX],AX          ; insert the keycode into the keyboard buffer
  262.         MOV     BX,DX            ; advance the tail
  263.         MOV     BUFFER_TAIL,BX   ; record its new position
  264.  
  265. NB_INT2F3:
  266.         STI                      ; enable interrupts
  267.     POP    DS               ; restore registers
  268.     POP    DX
  269.     POP    BX
  270.     POP    AX
  271.  
  272. NB_INT2F4:
  273.     POPF                     ; restore the caller's flags
  274.     DB    0EAH             ; JMP FAR immediate opcode
  275. INTADDR    DD    0             ; original int 2F address, updated by NB_START()
  276.  
  277. NB_INT2F ENDP
  278.  
  279. CODE    ENDS    ; end of segment
  280.         END     ; end of program
  281.